/*
 * Copyright (c) 2013 by Chances.
 * $CVSHeader$
 * $Author$
 * $Date$
 * $Revision$
 */
package chances.epg.navigator.service;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import chances.epg.navigator.context.AccessContext;
import chances.epg.navigator.template.TemplateConfig;
import chances.epg.navigator.template.TemplateContext;
import chances.epg.navigator.template.loader.TemplateConfigLoader;

/**
 * 模板配置参数.
 *
 * @author <a href="mailto:libf@chances.com.cn">libf</a>
 */

@Service
@EnableScheduling
public class TemplateConfigService {
	private static final String KEY_SEPERATOR = "$";
	private static final String DEFAULT_DETAIL_FIX = "_detail.jsp";

	public static final int INDEX_TYPE = 1;// 本频道页面
	public static final int LIST_TYPE = 2;// 子频道页面
	public static final int DETAIL_TYPE = 3;// 详情页面

	private Map<String, TemplateConfig> templateConfigMap;

	@Value("${epg.template.default:default}")
	String defaultPackage;
	
	@Autowired
	private TemplateConfigLoader templateConfigLoader;
	
	/*@Value("${epg.template.path}")
	private String templateRootPath;*/

	public TemplateConfigService() {
		templateConfigMap = new HashMap<String, TemplateConfig>();
	}

	@PostConstruct
	public void init(){
		this.reload();
	}
	/**
	 * 初始化模板配置.
	 * 
	 * @param templateConfigs
	 */
	
	@Scheduled(fixedDelay=1000*60*3)
	public void reload() {
		Collection<TemplateConfig> templateConfigs = this.templateConfigLoader.loadTemplateConfig();;
		Map<String, TemplateConfig> newMaps = new HashMap<String, TemplateConfig>();
		String key = null;
		for (TemplateConfig templateConfig : templateConfigs) {
			key = this.getKey(templateConfig);
			newMaps.put(key, templateConfig);
		}
		Map<String, TemplateConfig> oldMaps = this.templateConfigMap;
		this.templateConfigMap = newMaps;
		oldMaps.clear();
		oldMaps = null;
	}

	/**
	 * 获取所有的模板配置.
	 * 
	 * @return
	 */
	public Collection<TemplateConfig> getAllTemplateConfig() {
		Set<TemplateConfig> values = new HashSet<TemplateConfig>();
		CollectionUtils.addAll(values, templateConfigMap.values().iterator());
		return values;
	}

	/**
	 * 添加模板配置.
	 * 
	 * @param templateConfig
	 */
	public void addTemplateConfig(TemplateConfig templateConfig) {
		String key = this.getKey(templateConfig);
		this.templateConfigMap.put(key, templateConfig);
	}

	/**
	 * 删除模板配置.
	 * 
	 * @param templateConfig
	 */
	public void removeTemplateConfig(TemplateConfig templateConfig) {
		String key = this.getKey(templateConfig);
		this.templateConfigMap.remove(key);
	}

	/**
	 * 
	 * @param bizCode
	 * @return
	 */
	public TemplateConfig getSelfTemplateConfig(String bizCode) {
		String key = this.createKey(bizCode, INDEX_TYPE);
		return this.templateConfigMap.get(key);
	}

	/**
	 * 
	 * @param bizCode
	 * @param templateType
	 * @return
	 */
	public TemplateConfig getParentTemplateConfig(String bizCode) {
		String key = this.createKey(bizCode, LIST_TYPE);
		return this.templateConfigMap.get(key);
	}

	/**
	 * 详情页面模板配置
	 * 
	 * @param siteCode
	 * @param siteChannelCode
	 * @param contentType
	 * @return
	 */
	public TemplateConfig getTemplateConfigForDetail(String bizCode, String contentType) {
		String key = this.createKey(bizCode, contentType);
		return this.templateConfigMap.get(key);
	}

	/**
	 * 默认的详情页面模板. default模板包中，contentType + "_detail.jsp"，如：
	 * 
	 * @param siteCode
	 * @param contentType
	 * @return
	 */
	public TemplateConfig getDefaultTemplateConfigForDetail(String siteCode, String contentType) {
		TemplateConfig defaultConfig = new TemplateConfig();

		defaultConfig.setTemplatePackageCode(this.getDefaultPackage(siteCode));
		String templatePath = "/" + contentType + DEFAULT_DETAIL_FIX;
		defaultConfig.setTemplatePath(templatePath);
		defaultConfig.setTemplateType(DETAIL_TYPE + "");

		return defaultConfig;
	}

	/**
	 * 查找默认的模板包.
	 * 
	 * @param siteCode
	 * @return
	 */
	private String getDefaultPackage(String siteCode) {

		return defaultPackage;
	}

	/**
	 * 生成模板配置Key.
	 * 
	 * @param siteCode
	 * @param siteChannelCode
	 * @param templateType
	 * @return
	 */
	private String createKey(String bizCode, int templateType) {
		StringBuffer key = new StringBuffer(KEY_SEPERATOR);
		key.append(bizCode).append(KEY_SEPERATOR);
		key.append(templateType).append(KEY_SEPERATOR);
		return key.toString();
	}

	/**
	 * 生成模板配置Key.
	 * 
	 * @param siteCode
	 * @param siteChannelCode
	 * @param contentType
	 * @return
	 */
	private String createKey(String bizCode, String contentType) {
		StringBuffer key = new StringBuffer(KEY_SEPERATOR);
		key.append(bizCode).append(KEY_SEPERATOR);
		key.append(DETAIL_TYPE).append(KEY_SEPERATOR);
		key.append(contentType).append(KEY_SEPERATOR);

		return key.toString();
	}

	/**
	 * 模板配置Key
	 * 
	 * @param templateConfig
	 * @return
	 */
	private String getKey(TemplateConfig templateConfig) {
		StringBuffer key = new StringBuffer(KEY_SEPERATOR);
		key.append(templateConfig.getBizCode()).append(KEY_SEPERATOR);
		key.append(templateConfig.getTemplateType()).append(KEY_SEPERATOR);

		if (StringUtils.isNotEmpty(templateConfig.getContentType())) {
			key.append(templateConfig.getContentType()).append(KEY_SEPERATOR);
		}

		return key.toString();
	}

	 /* 
	 * @param config
	 * @return
	 */
	public TemplateContext createTemplateContext(TemplateConfig config, AccessContext accessContext) {
		TemplateContext context = new TemplateContext(config);
		context.setTemplateRootPath(accessContext.getSiteCode());
		return context;
	}
	
}
